package server

import (
	"context"
	"flag"
	"fmt"
	"net"
	"os"

	"example.com/dcache/cache"
	"example.com/dcache/logger"
	pb "example.com/dcache/rpcserver/dcacher"
	"example.com/dcache/setting"
	"google.golang.org/grpc"
)

type rpcserverServer struct {
	pb.UnimplementedDcacherServer
}

func (s *rpcserverServer) SetGroup(ctx context.Context, in *pb.SetGroupRequest) (*pb.SetGroupReply, error) {
	if err := cache.SetGroupLocal(in.GetGroup(), 0, nil); err != nil {
		logger.Error("<rpcserver> SetGroup %s: %s", in.GetGroup(), err)
		return nil, err
	}

	logger.Debug("<rpcserver> SetGroup %s", in.GetGroup())
	return &pb.SetGroupReply{Status: 200}, nil
}

func (s *rpcserverServer) DeleteGroup(ctx context.Context, in *pb.DeleteGroupRequest) (*pb.DeleteGroupReply, error) {
	cache.DeleteGroupLocal(in.GetGroup())
	logger.Debug("<rpcserver> DeleteGroup %s", in.GetGroup())
	return &pb.DeleteGroupReply{Status: 200}, nil
}

func (s *rpcserverServer) Set(ctx context.Context, in *pb.SetRequest) (*pb.SetReply, error) {
	if err := cache.Set(in.GetGroup(), in.GetKey(), []byte(in.GetValue())); err != nil {
		logger.Debug("<rpcserver> Set %s %s %s: %s", in.GetGroup(), in.GetKey(), in.GetValue(), err)
		return nil, err
	}

	logger.Debug("<rpcserver> Set %s %s %s", in.GetGroup(), in.GetKey(), in.GetValue())
	return &pb.SetReply{Status: 200}, nil
}
func (s *rpcserverServer) Get(ctx context.Context, in *pb.GetRequest) (*pb.GetReply, error) {
	if value, err := cache.Get(in.GetGroup(), in.GetKey()); err != nil {
		logger.Debug("<rpcserver> Get %s %s: %s", in.GetGroup(), in.GetKey(), err)
		return nil, err
	} else {
		logger.Debug("<rpcserver> Get %s %s", in.GetGroup(), in.GetKey())
		return &pb.GetReply{Status: 200, Value: string(value)}, nil
	}
}

func (s *rpcserverServer) Delete(ctx context.Context, in *pb.DeleteRequest) (*pb.DeleteReply, error) {
	if err := cache.Delete(in.GetGroup(), in.GetKey()); err != nil {
		logger.Debug("<rpcserver> Delete %s %s: %s", in.GetGroup(), in.GetKey(), err)
		return nil, err
	} else {
		logger.Debug("<rpcserver> Delete %s %s", in.GetGroup(), in.GetKey())
		return &pb.DeleteReply{Status: 200}, nil
	}
}

func Server() {
	//Parse port info from console input, default is 50051
	flag.Parse()

	//Listen the port
	hostname, _ := os.Hostname()
	lis, err := net.Listen("tcp", fmt.Sprintf("%s:%d", hostname, setting.ServerSetting.RpcPort))
	if err != nil {
		logger.Fatal("<rpcserver> server fails to listen: %s", err)
		panic(err)
	}

	logger.Info("<rpcserver> RPC server running at: %s", fmt.Sprintf("%s:%d", hostname, setting.ServerSetting.RpcPort))

	//Define rpc server
	s := grpc.NewServer()
	pb.RegisterDcacherServer(s, &rpcserverServer{})
	logger.Info("<rpcserver> Server listening at: %v", lis.Addr())

	//Run the rpc server with net.Listener
	if err := s.Serve(lis); err != nil {
		logger.Fatal("<rpcserver> grpc server fails to serve: %v", err)
		panic(err)
	}
}
